#include "wx/wxprec.h"
#include "wx/debugrpt.h"
#include "wx/filename.h"
#include "wx/ffile.h"
#include "wx/mimetype.h"
#include "wx/statline.h"

class wxDumpPreviewDlg : public wxDialog {
  public:
    wxDumpPreviewDlg( wxWindow *parent, const wxString& title, const wxString& text );
  private:
    wxTextCtrl *m_text;
    DECLARE_NO_COPY_CLASS( wxDumpPreviewDlg )
};

wxDumpPreviewDlg::wxDumpPreviewDlg( wxWindow *parent, const wxString& title, const wxString& text )
  : wxDialog( parent, wxID_ANY, title, wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER ) {
  m_text = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxPoint( 0, 0 ), wxDefaultSize, wxTE_MULTILINE | wxTE_READONLY | wxTE_NOHIDESEL | wxTE_RICH2 );
  m_text->SetValue( text );
  m_text->SetFont( wxFont( 12, wxFONTFAMILY_TELETYPE, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL ) );
  wxButton *btnClose = new wxButton( this, wxID_CANCEL, _( "Close" ) );
  wxSizer *sizerTop = new wxBoxSizer( wxVERTICAL ),
  *sizerBtns = new wxBoxSizer( wxHORIZONTAL );
  sizerBtns->Add( btnClose, 0, 0, 1 );
  sizerTop->Add( m_text, 1, wxEXPAND );
  sizerTop->Add( sizerBtns, 0, wxALIGN_RIGHT | wxTOP | wxBOTTOM | wxRIGHT, 1 );
  sizerTop->SetItemMinSize( m_text, 600, 300 );
  SetSizer( sizerTop );
  Layout();
  Fit();
  m_text->SetFocus();
}

class wxDumpOpenExternalDlg : public wxDialog {
  public:
    wxDumpOpenExternalDlg( wxWindow *parent, const wxFileName& filename );
    const wxString& GetCommand() const { return m_command; }
    wxString m_command;
  private:
    void OnBrowse( wxCommandEvent& event );
    DECLARE_EVENT_TABLE()
    DECLARE_NO_COPY_CLASS( wxDumpOpenExternalDlg )
};

BEGIN_EVENT_TABLE( wxDumpOpenExternalDlg, wxDialog )
  EVT_BUTTON( wxID_MORE, wxDumpOpenExternalDlg::OnBrowse )
END_EVENT_TABLE()

wxDumpOpenExternalDlg::wxDumpOpenExternalDlg( wxWindow *parent, const wxFileName& filename )
  : wxDialog( parent, wxID_ANY, wxString::Format( _( "打开文件 \"%s\"" ), filename.GetFullPath().c_str() ) ) {
  wxSizer *sizerTop = new wxBoxSizer( wxVERTICAL );
  sizerTop->Add( new wxStaticText( this, wxID_ANY, wxString::Format( _( "输入命令打开文件 \"%s\":" ), filename.GetFullName().c_str() ) ),
                 wxSizerFlags().Border() );
  wxSizer *sizerH = new wxBoxSizer( wxHORIZONTAL );
  wxTextCtrl *command = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 250, wxDefaultCoord ), 0
                                        , wxTextValidator( wxFILTER_NONE, &m_command ) );
  sizerH->Add( command, wxSizerFlags( 1 ).Align( wxALIGN_CENTER_VERTICAL ) );
  wxButton *browse = new wxButton( this, wxID_MORE, wxT( ">>" ), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT );
  sizerH->Add( browse, wxSizerFlags( 0 ).Align( wxALIGN_CENTER_VERTICAL ). Border( wxLEFT ) );
  sizerTop->Add( sizerH, wxSizerFlags( 0 ).Expand().Border() );
  sizerTop->Add( new wxStaticLine( this ), wxSizerFlags().Expand().Border() );
  sizerTop->Add( CreateStdDialogButtonSizer( wxOK | wxCANCEL ), wxSizerFlags().Align( wxALIGN_RIGHT ).Border() );
  SetSizer( sizerTop );
  Layout();
  Fit();
  command->SetFocus();
}

void wxDumpOpenExternalDlg::OnBrowse( wxCommandEvent& ) {
  wxFileName fname( m_command );
  wxFileDialog dlg( this, wxFileSelectorPromptStr, fname.GetPathWithSep(), fname.GetFullName() );
  if( dlg.ShowModal() == wxID_OK ) {
    m_command = dlg.GetPath();
    TransferDataToWindow();
  }
}


class wxDebugReportDialog : public wxDialog {
  public:
    wxDebugReportDialog( wxDebugReport& dbgrpt );
    virtual bool TransferDataToWindow();
    virtual bool TransferDataFromWindow();
  private:
    void OnView( wxCommandEvent& );
    void OnViewUpdate( wxUpdateUIEvent& );
    void OnOpen( wxCommandEvent& );
    static wxSizerFlags SizerFlags( int proportion ) {
      return wxSizerFlags( proportion ).Expand().Border();
    }
    wxDebugReport& m_dbgrpt;
    wxCheckListBox *m_checklst;
    wxTextCtrl *m_notes;
    wxArrayString m_files;
    DECLARE_EVENT_TABLE()
    DECLARE_NO_COPY_CLASS( wxDebugReportDialog )
};

BEGIN_EVENT_TABLE( wxDebugReportDialog, wxDialog )
  EVT_BUTTON( wxID_VIEW_DETAILS, wxDebugReportDialog::OnView )
  EVT_UPDATE_UI( wxID_VIEW_DETAILS, wxDebugReportDialog::OnViewUpdate )
  EVT_BUTTON( wxID_OPEN, wxDebugReportDialog::OnOpen )
  EVT_UPDATE_UI( wxID_OPEN, wxDebugReportDialog::OnViewUpdate )
END_EVENT_TABLE()

wxDebugReportDialog::wxDebugReportDialog( wxDebugReport& dbgrpt )
  : wxDialog( NULL, wxID_ANY,
              wxString::Format( _( "调试报告 \"%s\"" ), dbgrpt.GetReportName().c_str() ),
              wxDefaultPosition,
              wxDefaultSize,
              wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER ),
    m_dbgrpt( dbgrpt ) {
  wxString msg;
  wxString debugDir = dbgrpt.GetDirectory();
  msg << _( "已在目录中生成调试报告\n" )
      << _T( "   \"" ) << debugDir << _T( "\"\n" )
      << _T( '\n' )
      << _( "哦嚯 程序挂了吧 不服你钻进屏幕来打我呀 想知道什么原因吗不会看日志去\n" )
      << _( "看不懂吗?? 哦 你不会按确认键发送日志给我吗 发不出来???\n" )
      << _( "不知道先连接网络在按发送键 \n" )
      << _T( "\n\n" );
  const wxSizerFlags flagsFixed( SizerFlags( 0 ) );
  const wxSizerFlags flagsExpand( SizerFlags( 1 ) );
  const wxSizerFlags flagsExpand2( SizerFlags( 2 ) );
  wxSizer *sizerPreview = new wxStaticBoxSizer( wxVERTICAL, this, _( "调试报告:" ) );
  sizerPreview->Add( CreateTextSizer( msg ), SizerFlags( 0 ).Centre() );
  wxSizer *sizerFileBtns = new wxBoxSizer( wxVERTICAL );
  sizerFileBtns->AddStretchSpacer( 1 );
  sizerFileBtns->Add( new wxButton( this, wxID_VIEW_DETAILS, _( "预览..." ) ), wxSizerFlags().Border( wxBOTTOM ) );
  sizerFileBtns->Add( new wxButton( this, wxID_OPEN, _( "打开..." ) ), wxSizerFlags().Border( wxTOP ) );
  sizerFileBtns->AddStretchSpacer( 1 );
  m_checklst = new wxCheckListBox( this, wxID_ANY );
  wxSizer *sizerFiles = new wxBoxSizer( wxHORIZONTAL );
  sizerFiles->Add( m_checklst, flagsExpand );
  sizerFiles->Add( sizerFileBtns, flagsFixed );
  sizerPreview->Add( sizerFiles, flagsExpand2 );
  wxSizer *sizerNotes = new wxStaticBoxSizer( wxVERTICAL, this, _( "便笺:" ) );
  msg = _( "如果您有任何与此错误相关的附加信息，请报告, 请在这里输入，它将加入其中:" );
  m_notes = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE );
  sizerNotes->Add( CreateTextSizer( msg ), flagsFixed );
  sizerNotes->Add( m_notes, flagsExpand );
  wxSizer *sizerTop = new wxBoxSizer( wxVERTICAL );
  sizerTop->Add( sizerPreview, flagsExpand2 );
  sizerTop->AddSpacer( 5 );
  sizerTop->Add( sizerNotes, flagsExpand );
  sizerTop->Add( CreateStdDialogButtonSizer( wxOK | wxCANCEL ), flagsFixed );
  SetSizerAndFit( sizerTop );
  Layout();
  CentreOnScreen();
}

bool wxDebugReportDialog::TransferDataToWindow() {
  const size_t count = m_dbgrpt.GetFilesCount();
  for( size_t n = 0; n < count; n++ ) {
    wxString name, desc;
    if( m_dbgrpt.GetFile( n, &name, &desc ) ) {
      m_checklst->Append( name + _T( " (" ) + desc + _T( ')' ) );
      m_checklst->Check( n );
      m_files.Add( name );
    }
  }
  return true;
}

bool wxDebugReportDialog::TransferDataFromWindow() {
  const size_t count = m_checklst->GetCount();
  for( size_t n = 0; n < count; n++ ) {
    if( !m_checklst->IsChecked( n ) ) {
      m_dbgrpt.RemoveFile( m_files[n] );
    }
  }
  const wxString notes = m_notes->GetValue();
  if( !notes.empty() ) {
    m_dbgrpt.AddText( _T( "notes.txt" ), notes, _T( "user notes" ) );
  }
  return true;
}


void wxDebugReportDialog::OnView( wxCommandEvent& ) {
  const int sel = m_checklst->GetSelection();
  wxCHECK_RET( sel != wxNOT_FOUND, _T( "invalid selection in OnView()" ) );
  wxFileName fn( m_dbgrpt.GetDirectory(), m_files[sel] );
  wxString str;
  wxFFile file( fn.GetFullPath() );
  if( file.IsOpened() && file.ReadAll( &str ) ) {
    wxDumpPreviewDlg dlg( this, m_files[sel], str );
    dlg.ShowModal();
  }
}

void wxDebugReportDialog::OnOpen( wxCommandEvent& ) {
  const int sel = m_checklst->GetSelection();
  wxCHECK_RET( sel != wxNOT_FOUND, _T( "invalid selection in OnOpen()" ) );
  wxFileName fn( m_dbgrpt.GetDirectory(), m_files[sel] );
  wxString command;
  wxFileType * ft = wxTheMimeTypesManager->GetFileTypeFromExtension( fn.GetExt() );
  if( ft ) {
    command = ft->GetOpenCommand( fn.GetFullPath() );
    delete ft;
  }
  if( command.empty() ) {
    wxDumpOpenExternalDlg dlg( this, fn );
    if( dlg.ShowModal() == wxID_OK ) {
      wxString cmd = dlg.GetCommand();
      if( !cmd.empty() ) {
        if( cmd.find( _T( '%' ) ) != wxString::npos ) {
          command = wxFileType::ExpandCommand( cmd, fn.GetFullPath() );
        } else {
          command << cmd << _T( " \"" ) << fn.GetFullPath() << _T( '"' );
        }
      }
    }
  }
  if( !command.empty() ) {
    ::wxExecute( command );
  }
}

void wxDebugReportDialog::OnViewUpdate( wxUpdateUIEvent& event ) {
  int sel = m_checklst->GetSelection();
  if( sel >= 0 ) {
    wxFileName fn( m_dbgrpt.GetDirectory(), m_files[sel] );
    event.Enable( fn.FileExists() );
  } else {
    event.Enable( false );
  }
}

bool wxDebugReportPreviewStd::Show( wxDebugReport& dbgrpt ) const {
  if( !dbgrpt.GetFilesCount() ) {
    return false;
  }
  wxDebugReportDialog dlg( dbgrpt );
  return dlg.ShowModal() == wxID_OK && dbgrpt.GetFilesCount() != 0;
}
